#pragma once
#include <stdio.h>
#include <stdint.h>
#include <sm3.h>
#include <sm2_bn.h>

typedef struct {
    sm2_bn_point_type public_key;
    sm2_bn_type private_key;
} SM2_KEY;

int sm2_key_generator(SM2_KEY *key);

int sm2_key_printf( const char *label, const SM2_KEY *key);

typedef struct {
    uint8_t r[32];
    uint8_t s[32];
} SM2_SIGNATURE;

typedef struct {
    sm2_bn_type k;
    sm2_bn_type x1_mod_n;
} SM2_SIGN_PRE_COMP;

#define SM2_SIGN_PRE_COMP_COUNT 32
#define SM2_MAX_SIGNATURE_SIZE 72

int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *out_len);

int sm2_printf_signature(const char *label, const SM2_SIGNATURE *sig);


#define SM2_DEFAULT_ID		"1234567812345678"
#define SM2_DEFAULT_ID_LENGTH	(sizeof(SM2_DEFAULT_ID) - 1)  // LENGTH for string and SIZE for bytes
#define SM2_MAX_ID_BITS		65535
#define SM2_MAX_ID_LENGTH	(SM2_MAX_ID_BITS/8)


typedef struct {
    SM3_CTX sm3_ctx;
    SM3_CTX saved_sm3_ctx;
    SM2_KEY key;
    sm2_bn_type fast_sign_private;
    SM2_SIGN_PRE_COMP pre_comp[SM2_SIGN_PRE_COMP_COUNT];
    unsigned int num_pre_comp;
    sm2_bn_point_type public_point_table[16]; // verify public point table, P, 2P, ..., 16P
} SM2_SIGN_CTX;

typedef struct {
    SM3_CTX sm3_ctx;
    SM3_CTX saved_sm3_ctx;
    SM2_KEY key;
    sm2_bn_point_type public_point_table[16];
} SM2_VERIFY_CTX;

int sm2_signature(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, const size_t id_len, const uint8_t *data,
                  size_t data_len, uint8_t *sig, size_t *sig_len, SM2_SIGNATURE *signature);

int sm2_verify(SM2_VERIFY_CTX *ctx, const SM2_KEY *key, const char *id, const size_t id_len, const uint8_t *data,
               size_t data_len, const SM2_SIGNATURE *signature);
